<?php

defined('IN_XLP') or die('Access Denied');

/*
 * 2017-07-12 微信申请退款接口
 * add by hsisme
 * 文档地址：http://mch.weixin.qq.com/wiki/doc/api/index.php?chapter=9_1
 */

class weixinRefund {

    //统一下单地址
    const HONGBAO_URL = 'https://api.mch.weixin.qq.com/secapi/pay/refund';

    //交易类型
    //微信基本参数
    private $appid;
    private $mch_id;    //原partner_id
    private $partner_key;
    private $paysign_key;
    private $debug;
    //支付通知URL
    private $notify_url;
    //运行时间
    private $runtime;
    private $sslcert_path;
    private $sslcert_key;


    public function __construct($p = array()) {
        //$this->notify_url = U('wxpay/notify/index');
        $this->runtime = date('Y-m-d H:i:s', TIME);

        $this->appid = isset($p['appid']) ? $p['appid'] : '';
        $this->mch_id = isset($p['partner_id']) ? $p['partner_id'] : '';
        $this->partner_key = isset($p['partner_key']) ? $p['partner_key'] : '';
        $this->paysign_key = isset($p['paysign_key']) ? $p['paysign_key'] : '';
        $this->debug = false;
        if (!($this->appid && $this->mch_id && $this->partner_key && $this->paysign_key)) {
            $userInfo = F('weixin/setting');
            $wxpayConfig = C('app/pay');
            if (isHave($userInfo['user_info']['wx_AppId']) && isHave($userInfo['user_info']['wx_PartnerId']) && isHave($userInfo['user_info']['wx_PartnerKey']) && isHave($userInfo['user_info']['wx_PaySignKey'])) {
                //设置微信基本参数
                $this->appid = $userInfo['user_info']['wx_AppId'];
                $this->mch_id = $userInfo['user_info']['wx_PartnerId'];
                $this->partner_key = $userInfo['user_info']['wx_PartnerKey'];
                $this->paysign_key = $userInfo['user_info']['wx_PaySignKey'];
                $this->sslcert_path = $wxpayConfig['wxpay']['sslcert_path'];
                $this->sslcert_key  = $wxpayConfig['wxpay']['sslcert_key'];
            } else {
                throw new Exception($this->runtime . 'Error:请设置好所有的微信参数');
            }
        }
    }

    /**
     * 微信申请退款接口 add by hsisme
     * 
     * @param  array  $order_params 订单各类参数
     * @param  int    $type         交易类型
     * @return
     */
    public function refund($info, $debug = false) {
            $objData['appid']          = $this->appid;
            $objData['mch_id']         = $this->mch_id;
            $objData['nonce_str']      = getRandStr();
            $objData['out_refund_no']  = $info['out_refund_no'];
            $objData['transaction_id'] = $info['transaction_id'];
            $objData['total_fee']      = intval($info['service']*100);
            $objData['refund_fee']     = intval($info['service']*100);
            $objData['sign']           = $this->getMD5Sign($objData);
            $xml = $this->arrayToXml($objData);
            $data = $this->curl_post_ssl(self::HONGBAO_URL, $xml);
        
            if (!$data) {
                saveLog('weixin/refundError', '接口通讯失败');
                return false;
            }
            $result = (array) simplexml_load_string($data, 'SimpleXMLElement', LIBXML_NOCDATA);

            if ($debug) {
                saveLog('weixin/refundLog', array('data' => $objData, 'send' => $xml, 'result' => $data));
                return false;
            }
            
            if($result['return_code'] == 'SUCCESS'){
                M('order')->update(array('out_refund_no'=>$info['out_refund_no']) , array('id' => $info['id']));
                saveLog('weixin/refundLog', array('data' => $objData, 'send' => $xml, 'result' => $result));
                return true;
            }else{
                saveLog('weixin/refundError', array('data' => $objData, 'send' => $xml, 'result' => $result,'err_code' => $result['err_code']));
                return false;
            }
    }

    /*
     * 参数签名
     */

    private function getMD5Sign($array = array()) {
        //空值不签名
        ksort($array);
        $str = '';
        foreach ($array as $k => $v) {
            if ($v) {
                $str .= $k . '=' . $v . '&';
            }
        }
        $key = $this->partner_key;
        $signStr = $str . 'key=' . $key;
        return strtoupper(md5($signStr));
    }

    public function arrayToXml($arr) {
        $xml = '<xml>';
        foreach ($arr as $key => $val) {
            if (is_numeric($val)) {
                $xml.='<' . $key . '>' . $val . '</' . $key . '>';
            } else {
                $xml.='<' . $key . '><![CDATA[' . $val . ']]></' . $key . '>';
            }
        }
        $xml.='</xml>';
        return $xml;
    }

    public function curl_post_ssl($url, $vars, $second = 30, $aHeader = array()) {
        $ch = curl_init();
        //超时时间
        curl_setopt($ch, CURLOPT_TIMEOUT, $second);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        //这里设置代理，如果有的话
        //curl_setopt($ch,CURLOPT_PROXY, '10.206.30.98');
        //curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

        //以下两种方式需选择一种
        //第一种方法，cert 与 key 分别属于两个.pem文件
        //curl_setopt($ch,CURLOPT_SSLCERT,getcwd().'/apiclient_cert.pem');
        //curl_setopt($ch,CURLOPT_SSLKEY,getcwd().'/apiclient_key.pem');
        curl_setopt($ch, CURLOPT_SSLCERT, $this->sslcert_path);
        curl_setopt($ch, CURLOPT_SSLKEY,  $this->sslcert_key);
        // curl_setopt($ch, CURLOPT_CAINFO, '/www/cert/rootca.pem');

        //第二种方式，两个文件合成一个.pem文件
        //curl_setopt($ch,CURLOPT_SSLCERT,getcwd().'/all.pem');

        if (count($aHeader) >= 1) {
            curl_setopt($ch, CURLOPT_HTTPHEADER, $aHeader);
        }

        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $vars);
        $data = curl_exec($ch);
        if (curl_errno($ch)) {
            saveLog('https/error', 'Curl Error:url:' . $url . ' ,info:' . curl_error($ch));
            $data = null;
        }
        curl_close($ch);
        return $data;
    }

}
